package com.yangj.service;

import com.yangj.test.*;
import com.yangj.util.*;
import org.dom4j.io.*;
import org.dom4j.*;
import com.baidu.aip.ocr.*;
import net.sf.json.*;
import com.thoughtworks.xstream.*;
import java.util.*;
import com.yangj.entity.*;
import java.net.*;
import java.io.*;

public class WeChatVerifyService
{
    private static final String TOKEN;
    
    //微信公众号
    private static final String GET_TOKEN_URL;
    private static final String APPID;
    private static final String APPSECRET;
    
    // 腾讯智能闲聊
    private static final String ROBOT_APPID;
    private static final String ROBOT_APPKEY;
    private static final String ROBOT_URL;
    
    private static AccessToken at;
    private static final String MENU_URL;
    
    //百度 ai 
    public static final String BAIDU_APP_ID;
    public static final String BAIDU_API_KEY;
    public static final String BAIDU_SECRET_KEY;
    
    static {
        final Properties properties = new Properties();
        final InputStream in = TestProperty.class.getClassLoader().getResourceAsStream("wechatConfig.properties");
        try {
            properties.load(in);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(properties);
        TOKEN = properties.getProperty("TOKEN");
        
        ROBOT_APPID = properties.getProperty("ROBOT_APPID");
        ROBOT_APPKEY = properties.getProperty("ROBOT_APPKEY");
        ROBOT_URL = properties.getProperty("ROBOT_URL");
        
        GET_TOKEN_URL = properties.getProperty("GET_TOKEN_URL");
        APPID = properties.getProperty("APPID");
        APPSECRET = properties.getProperty("APPSECRET");
        
        MENU_URL = properties.getProperty("MENU_URL");
        
        BAIDU_APP_ID = properties.getProperty("BAIDU_APP_ID");
        BAIDU_API_KEY = properties.getProperty("BAIDU_API_KEY");
        BAIDU_SECRET_KEY = properties.getProperty("BAIDU_SECRET_KEY");
    }
    
    public static String getMenuUrl() {
        return MENU_URL;
    }
    
    public static String getAppid() {
        return APPID;
    }
    

    public static String getAppsecret() {
		return APPSECRET;
	}
    /*
     * 获得token
     * */
    private static void getToken() {
        final String url = WeChatVerifyService.GET_TOKEN_URL.replace("APPID", WeChatVerifyService.APPID).replace("APPSECRET", WeChatVerifyService.APPSECRET);
        final String tokenStr = MyUtils.get(url);
        final JSONObject jsonObject = JSONObject.fromObject((Object)tokenStr);
        final String token = jsonObject.getString("access_token");
        final String expireIn = jsonObject.getString("expires_in");
        //创建token对象，并存起来
        at = new AccessToken(token, expireIn);
    }
    
    /*
     * 向外暴露 获取access_token方法
     * */
    public static String getAccessToken() {
        if (WeChatVerifyService.at == null || WeChatVerifyService.at.isExpired()) {
            getToken();
        }
        return WeChatVerifyService.at.getAccessToken();
    }
    
    /*
     * 验证消息的确来自微信服务器
     * */
    public static boolean check(final String timestamp, final String nonce, final String signature) {
    	//1）将token、timestamp、nonce三个参数进行字典序排序
        final String[] strs = { WeChatVerifyService.TOKEN, timestamp, nonce };
        Arrays.sort(strs);
      //2）将三个参数字符串拼接成一个字符串进行sha1加密
        final String str = String.valueOf(strs[0]) + strs[1] + strs[2];
        final String mysig = MyUtils.sha1Encrype(str);
      //3）开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
        System.out.println(mysig);
        System.out.println(signature);
        return signature.equalsIgnoreCase(mysig);
    }
    
    /*
     * 输入流数据使用map 存储
     * */
    public static Map<String, String> parseRequest(final InputStream is) {
        final Map<String, String> map = new HashMap<String, String>();
        final SAXReader reader = new SAXReader();
        try {
			//读取输入流，获取文档对象
			Document document = reader.read(is);
			//根据文档对象获取根节点
			Element root = document.getRootElement();
			//根据根节点获取所有子节点
			List<Element> elements = root.elements();
			for(Element e : elements){
				map.put(e.getName(), e.getStringValue());
			}
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		return map;
    }
    
    /*
     * 对接受到的信息进行响应
     * */
    public static String getResponse(final Map<String, String> requestMap) {
        BaseMessage baseMsg = null;
        final String msgType = requestMap.get("MsgType");
        // FromUserName 和 ToUserName 需互换
        final String temp = requestMap.get("FromUserName");
        requestMap.put("FromUserName", requestMap.get("ToUserName"));
        requestMap.put("ToUserName", temp);
        final String s;
        switch (s = msgType) {
            case "news": {
                break;
            }
            //处理文本消息
            case "text": {
                baseMsg = dealTextMessage(requestMap);
                break;
            }
            case "event": {
                baseMsg = dealEventMessage(requestMap);
                break;
            }
            case "image": {
                baseMsg = dealImageMessage(requestMap);
                break;
            }
            case "music": {
                break;
            }
            case "video": {
                break;
            }
            case "voice": {
                break;
            }
            default:
                break;
        }
        
        //把消息对象处理为xml数据包
        if (baseMsg != null) {
            return beanToXml(baseMsg);
        }
        return null;
    }
    
    /*
     * 百度AI  图片文字识别
     * */
    private static BaseMessage dealImageMessage(Map<String, String> requestMap) {
		// 初始化一个AipOcr
        AipOcr client = new AipOcr(BAIDU_APP_ID, BAIDU_API_KEY, BAIDU_SECRET_KEY);

        // 调用接口
        String path = requestMap.get("PicUrl");
        //本地图片
       // org.json.JSONObject res = client.basicGeneral(path, new HashMap<String, String>());
       // System.out.println(res.toString(2));
        //远程图片
        org.json.JSONObject res = client.basicGeneralUrl(path, new HashMap<String, String>());
        System.out.println(res.toString(2));
        String json = res.toString(2);
        //转为jsonObject
        JSONObject jsonObject = JSONObject.fromObject(json);
        JSONArray jsonArray= jsonObject.getJSONArray("words_result");
        Iterator<JSONObject> it = jsonArray.iterator();
        StringBuilder sb = new StringBuilder();
        while( it.hasNext()){
        	JSONObject next = it.next();
        	sb.append(next.getString("words"));
        }
		return new TextMessage(requestMap, sb.toString());
	}
    
    /*
	 * 处理菜单事件
	 * */
    private static BaseMessage dealEventMessage(final Map<String, String> requestMap) {
        final String event = requestMap.get("Event");
        final String s;
        switch (s = event) {
            case "VIEW": {
                return dealView(requestMap);
            }
            case "CLICK": {
                return dealClick(requestMap);
            }
            default:
                break;
        }
        return null;
    }
    
    /*
	 * 处理View类型菜单
	 * */
    private static BaseMessage dealView(final Map<String, String> requestMap) {
        return null;
    }
    
    /*
	 * 处理Click类型菜单
	 * */
    private static BaseMessage dealClick(final Map<String, String> requestMap) {
        final String key = requestMap.get("EventKey");
        final String s;
        switch(key){
		case "1":
			//处理点击了第一个一级菜单
			return new TextMessage(requestMap, "您点击了第一个一级菜单");
		case "31":
			//处理点击了第三个一级菜单的第一个子菜单
			break;
		case "32":
			//处理点击了第三个一级菜单的第一个子菜单
			break;
		}
        return null;
    }
    
    /*
	 * 把消息对象处理成xml数据包
	 * */
	private static String beanToXml(BaseMessage baseMsg) {
		XStream xStream = new XStream();
		//使注解生效
		xStream.processAnnotations(TextMessage.class);
		xStream.processAnnotations(ImageMessage.class);
		xStream.processAnnotations(MusicMessage.class);
		xStream.processAnnotations(NewsMessage.class);
		xStream.processAnnotations(VideoMessage.class);	
		xStream.processAnnotations(VoiceMessage.class);
		String xml = xStream.toXML(baseMsg);
		return xml;
	}
    
	
    private static BaseMessage dealTextMessage(final Map<String, String> requestMap) {
    	//用户发来的内容
        final String msg = requestMap.get("Content");
        if ("登录".equals(msg)) {
            final String redirectUrl = "http://hello.cn1.utools.club/wechat_yangj/GetUserInfo";
            String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=yangj";
            url = url.replace("APPID", WeChatVerifyService.APPID).replace("REDIRECT_URI", redirectUrl);
            final TextMessage tm = new TextMessage(requestMap, "点击<a href=\"" + url + "\">这里</a>登录");
            return tm;
        }
        if ("图文".equals(msg)) {
            final List<Article> articles = new ArrayList<Article>();
            articles.add(new Article("晴空万里", "有是一个好天气", 
            		"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fwww.08lr.cn%2Fuploads%2Fallimg%2F170513%2F1-1F513164126.jpg&refer=http%3A%2F%2Fwww.08lr.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1615127735&t=d9ea370db2d86bd6436693af71682d88", 
            		"https://gityang2016.gitee.io/"));
            requestMap.put("MsgType", "news");
            final NewsMessage newsMessage = new NewsMessage(requestMap, articles);
            return newsMessage;
        }
        final String resp = ChatRobot(msg);
        System.out.println(resp);
        final TextMessage tm2 = new TextMessage(requestMap, resp);
        return tm2;
    }
    
    /*
     * 腾讯AI 智能闲聊
     * */
    private static String ChatRobot(final String msg) {
        String result = null;
        final Map<String, String> tempParamS = new HashMap<String, String>();
        try {
            tempParamS.put("app_id", WeChatVerifyService.ROBOT_APPID);
            tempParamS.put("time_stamp", System.currentTimeMillis() /1000 +""); //请求时间戳(秒)
            tempParamS.put("nonce_str", "ahappyman007");  //随机字符串
            tempParamS.put("sign", "");  //签名信息
            tempParamS.put("session", "1230321");  //会话标识
            tempParamS.put("question", msg);		//用户输入的聊天内容
            final Map<String, String> signMap = (Map<String, String>)MyUtils.getSignature((Map)tempParamS, WeChatVerifyService.ROBOT_APPKEY);
            result = MyUtils.net(WeChatVerifyService.ROBOT_URL, (Map)signMap, "GET");
            final JSONObject jsonObject = JSONObject.fromObject((Object)result);
            final int code = jsonObject.getInt("ret");
            System.out.println(jsonObject);
            if (code == 0) {
                final String resp = jsonObject.getJSONObject("data").getString("answer");
                return resp;
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /*
     * 上传临时素材
     * */
    public static String upload(String path,String type){
		File file = new File(path);
		//地址
		String url ="https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";
		url = url.replace("ACCESS_TOKEN", getAccessToken()).replace("TYPE", type);
		try {
			URL urlObj = new URL(url);
			//强转为安全连接
			HttpURLConnection conn = (HttpURLConnection) urlObj.openConnection();
			//设置连接的信息
			conn.setDoInput(true);
			conn.setDoOutput(true);
			conn.setUseCaches(false);
			//设置请求头信息
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("Charset", "utf8");
			//数据的边界
			String boundary = "-----" +System.currentTimeMillis();
			conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" +boundary);
			//获取输出流
			OutputStream out = conn.getOutputStream();
			//创建文件的输入流
			InputStream is = new FileInputStream(file);
			//第一部分: 头部信息
			//准备头部信息
			//准备头部消息
			StringBuilder sb = new StringBuilder();
			sb.append("--");
			sb.append(boundary);
			sb.append("\r\n");
			sb.append("Content-Disposition:form-data;name="+ "\"media\";filename=\""+ file.getName() + "\"\r\n");
			sb.append("Content-Type:application/octet-stream\r\n\r\n");
			out.write(sb.toString().getBytes());
			System.out.println("head: "+ sb.toString());
			//第二部分:文件内容
			byte[] b = new byte[1024];
			int len;
			while((len = is.read(b))!=-1){
				out.write(b,0,len);
			}
			//第三部分
			String foot = "\r\n--" + boundary +"--\r\n";
			out.write(foot.getBytes());
			out.flush();
			out.close();
			//读取数据
			InputStream is2 = conn.getInputStream();
			StringBuilder resp = new StringBuilder();
			while((len = is2.read(b))!= -1){
				resp.append(new String(b,0,len));
			}
			return resp.toString();
		} catch (Exception e) {
			
			e.printStackTrace();
		}
		return null;
	}
    
    
   
    /*
     * 获取带参数二维码的ticket
     * */
    public static String getQrCodeTicket() {
        final String at = getAccessToken();
        final String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + at;
        //生成临时字符二维码
        final String data = "{\"expire_seconds\": 120, \"action_name\": \"QR_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"yangj\"}}}";
        final String result = MyUtils.post(url, data);
        final String ticket = JSONObject.fromObject((Object)result).getString("ticket");
        return ticket;
    }
    
    /*获取用户基本信息
     * 
     * */
    public static String getUserInfo(final String openid) {
        String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
        url = url.replace("ACCESS_TOKEN", getAccessToken()).replace("OPENID", openid);
        System.out.println("url: " + url);
        final String result = MyUtils.get(url);
        return result;
    }
    
    
    

    /*
     * xml 去空格(不需要)
     * */
    private static String xmlFormat(final String str) {
        boolean flag = true;
        final StringBuffer ans = new StringBuffer();
        String tmp = "";
        for (int i = 0; i < str.length(); ++i) {
            if ('<' == str.charAt(i)) {
                tmp = tmp.trim();
                ans.append(tmp);
                flag = true;
                ans.append(str.charAt(i));
            }
            else if ('>' == str.charAt(i)) {
                flag = false;
                ans.append(str.charAt(i));
                tmp = "";
            }
            else if (flag) {
                ans.append(str.charAt(i));
            }
            else {
                tmp = String.valueOf(tmp) + str.charAt(i);
            }
        }
        return ans.toString();
    }
}
